<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/27 0027
 * Time: 22:09
 */

namespace App\Listener;

use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use Firebase\JWT\SignatureInvalidException;
use Lib\Core\ConfigLoad;

/**
 * @Listener(ws.hand)
 * @description:
 * @auth:yfl
 * @email:554665488@qq.com
 * Class OpenListener
 * @package App\Listener
 */
class HandshakeListener
{
    public function handel($params)
    {
//        $redis = new \Redis();
//        $redis->hSetNx()
//        var_dump("握手事件触发");
        $request = $params['request'];
        $response = $params['response'];
        $redis = $params['redis'];
        $server = $params['server'];
        if (!isset($request->header['sec-websocket-protocol'])) {
            $response->end();
            return false;
        }
        try {
            $token = $request->header['sec-websocket-protocol'];
            $config = ConfigLoad::getInstance();
            $config->load();//载入配置文件

            $key = $config::get('JwT_key');
            $arr = JWT::decode($token, $key, ['HS256']);
            $userInfo = $arr->data;
            $serviceIpPort = $userInfo->service_url;
            //绑定路由关系,通过id来查找fd
            $res = $redis->hSetNx($serviceIpPort, 'uid_' . $userInfo->uid, json_encode(['fd' => $request->fd, 'name' => $userInfo->name]));
            if (!$res) echo '用户已经连接服务';
        } catch (SignatureInvalidException $e) { //签名错误
            echo '签名错误';
            throw new \Exception($e->getMessage());
        } catch (ExpiredException $e) { //过期
            echo '过期';
            throw new \Exception($e->getMessage());
        } catch (\Exception $e) {
            echo '1234';
            throw new \Exception($e->getMessage());
        }
        //token认证成功然后握手
        $secWebSocketKey = $request->header['sec-websocket-key'];
        $patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
        if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
            $response->end();
            return false;
        }
//        echo $request->header['sec-websocket-key'];
        $key = base64_encode(sha1(
            $request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
            true
        ));

        $headers = [
            'Upgrade' => 'websocket',
            'Connection' => 'Upgrade',
            'Sec-WebSocket-Accept' => $key,
            'Sec-WebSocket-Version' => '13',
        ];
        // WebSocket connection to 'ws://127.0.0.1:9502/'
        // failed: Error during WebSocket handshake:
        // Response must not include 'Sec-WebSocket-Protocol' header if not present in request: websocket
        if (isset($request->header['sec-websocket-protocol'])) {
            $headers['Sec-WebSocket-Protocol'] = $request->header['sec-websocket-protocol'];
        }

        foreach ($headers as $key => $val) {
            $response->header($key, $val);
        }
        $response->status(101);
//        $server->push($request->fd,json_encode(['msg'=>'握手成功']));
        $response->end();
    }
}